﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Milan.Deploy
{
	/// <summary>
	/// The client object is used to establish a connection with the "Deploy Script" on the server.
	/// </summary>
	public partial class Client
	{
		public Client(ReleaseType releaseType, string productName, Uri[] urlList, Version currentVersion)
		{
			m_releaseType = releaseType;
			m_productName = productName;
			m_urlList = urlList;
			m_currentVersion = currentVersion;
		}
		public Client() : this(Assembly.GetEntryAssembly())
		{
		}
		public Client(Assembly assembly)
		{
			m_releaseType = Settings.ReleaseTypeSubscription;
			m_productName = ((AssemblyProductAttribute)(assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false)[0])).Product;
			var attribute = assembly.GetCustomAttributes(typeof(Milan.Reflection.AssemblyCommentAttribute), false);
			if (attribute.Length > 0)
			{
				var urlAtrribute = ((Milan.Reflection.AssemblyCommentAttribute)(attribute[0]));
				string[] urls = urlAtrribute.Comment.Split(',');
				m_urlList = new Uri[urls.Length];
				for (int i = 0; i < urls.Length; ++i)
					m_urlList[i] = new Uri(urls[i]);
			}
			else
				m_urlList = new Uri[0];
			m_currentVersion = assembly.GetName().Version;
		}
		/// <summary>
		/// Set the security token
		/// </summary>
		public string SecurityToken { get; set; }
		/// <summary>
		/// Fill the upload script URI's
		/// </summary>
		public Uri[] UploadScriptUris
		{
			get
			{
				Uri[] uploadScriptUris = new Uri[m_urlList.Length];
				for (var i = 0; i < uploadScriptUris.Length; ++i)
				{
					try
					{
						var UploadScript = Milan.Net.Download.GetTextFile(new Uri(m_urlList[i],"milan.txt")).Trim();
						uploadScriptUris[i] = new Uri(m_urlList[i], UploadScript);
					}
					catch (WebException)
					{
						// Just leave it empty, if we can't get it.
					}
				}
				return uploadScriptUris;
			}
		}
		public ReleaseType ReleaseType
		{
			get { return m_releaseType; }
		}
		protected ReleaseType m_releaseType;
		public string ProductName
		{
			get { return m_productName; }
		}
		private string m_productName;
		public Uri[] UrlList
		{
			get { return m_urlList; }
		}
		private Uri[] m_urlList;
		public Version CurrentVersion
		{
			get { return m_currentVersion; }
		}
		private Version m_currentVersion;
		/// <summary>
		/// Helper function to format the end part of the version directory
		/// </summary>
		/// <param name="version"></param>
		/// <returns></returns>
		public static string FormatVersionDirectory(Version version)
		{
			return "v" + version.Major + "_" + version.Minor + "_" + version.Build + "_" + version.Revision;
		}
		/// <summary>
		/// Helper function to format a URI friendly product name
		/// </summary>
		/// <param name="productName">The actual official product name</param>
		/// <returns>The URI friendly name</returns>
		protected static string FormatUriFriendlyProductName(string productName)
		{
			return productName.Replace('.', '_').Replace(' ', '_');
		}
		/// <summary>
		/// Gets the URI to the product directory
		/// </summary>
		/// <param name="downloadUrl">Full URL to the download directory</param>
		/// <returns>URI to product directory</returns>
		protected Uri FormatProductUri(Uri downloadUrl)
		{
			return new Uri(downloadUrl, "products/"+FormatUriFriendlyProductName(m_productName) + "/");
		}
		/// <summary>
		/// Returns the URI to the full base version directory
		/// </summary>
		/// <param name="downloadUrl"></param>
		/// <param name="version"></param>
		/// <returns></returns>
		protected Uri FormatVersionUri(Uri downloadUrl, Version version)
		{
			return new Uri(FormatProductUri(downloadUrl), FormatVersionDirectory(version) + "/");
		}
		/// <summary>
		/// Gets the full URL of the given release information text file
		/// </summary>
		/// <param name="downloadUrl">The root download URL</param>
		/// <returns></returns>
		protected Uri GetReleaseTextFileUrl(Uri downloadUrl)
		{
			return GetReleaseTextFileUrl(downloadUrl,m_releaseType);
		}
		/// <summary>
		/// Gets a particular version of ReleaseType text file
		/// </summary>
		/// <param name="downloadUrl"></param>
		/// <param name="releaseType"></param>
		/// <returns></returns>
		protected Uri GetReleaseTextFileUrl(Uri downloadUrl, ReleaseType releaseType)
		{
			return new Uri(FormatProductUri(downloadUrl), GetReleaseTypeName(releaseType) + ".txt");
		}
		/// <summary>
		/// Gets the name of the release type suitable for a file name
		/// </summary>
		/// <param name="releaseType">The release Type</param>
		/// <returns>A string with alpha, beta or release</returns>
		protected static string GetReleaseTypeName(ReleaseType releaseType)
		{
			return releaseType.ToString().ToLower();
		}
		/// <summary>
		/// This prepares the post vars for the upload script on the server
		/// </summary>
		/// <param name="op">OpCode - What this post will do, upload or setreleasetype</param>
		/// <param name="destination">Relative product</param>
		/// <returns></returns>
		protected NameValueCollection SetPostVars(OpCodes op, string destination)
		{
			NameValueCollection postVars = new NameValueCollection(4);
			postVars.Add("op", op.ToString());
			postVars.Add("product", ProductName);
			postVars.Add("version", CurrentVersion.ToString());
			if (destination != null)
				postVars.Add("dest", destination);
			postVars.Add("token", SecurityToken);
			postVars.Add("machineid",Settings.MachineId.ToString("N"));
			return postVars;
		}

	}
}
